import { customRef, watch } from 'vue'

import type { IEventDebounce } from '../../types/20-form-item'

/**
 * 控件的防抖输入
 * @param props 组件的 props
 * @param emit 组件的 emit
 * @param key v-model的名称，默认 modelValue，用于emit
 * @param events 事件集合，run：立即提交；clear：清空计时，用于汉字输入
 * @param delay 延迟时间，默认500毫秒
 */
export default function debounceRef<T, K extends keyof T> 
(
  props: T,
  emit: (event: any, ...args: any[]) => void,
  key: K,
  events: IEventDebounce,
  delay = 500
) {
  
  // const _key = (key) ?? 'modelValue'

  // 计时器
  let timeout: NodeJS.Timeout
  // 初始化设置属性值
  let _value = props[key]

  // 立即提交的事件
  events.run = () => {
    // 清掉上一次的计时
    clearTimeout(timeout)
    // 立即提交
    emit(`update:${key.toString()}`, _value)
  }

  // 清掉上次计时，用于汉字的连续输入
  events.clear = () => {
    clearTimeout(timeout) // 清掉上一次的计时
  }
  
  return customRef<T[K]>((track: () => void, trigger: () => void) => {
    // 监听父组件的属性变化，然后赋值，确保响应父组件设置属性
    watch(() => props[key], (v1) => {
      _value = v1
      trigger()
    })

    return {
      get(): T[K] {
        track()
        return _value
      },
      set(val: T[K]) {
        _value = val // 绑定值
        trigger() // 输入内容绑定到控件，但是不提交
        clearTimeout(timeout) // 清掉上一次的计时
        // 设置新的计时
        timeout = setTimeout(() => {
          emit(`update:${key.toString()}`, val) // 提交
        }, delay)
      }
    }
  })
}
